home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 68K / Lib / ntpath.py < prev    next >
Text File  |  1996-05-20  |  9KB  |  348 lines

  1. # Module 'ntpath' -- common operations on DOS pathnames
  2.  
  3. import os
  4. import stat
  5. import string
  6.  
  7.  
  8. # Normalize the case of a pathname.
  9. # On MS-DOS it maps the pathname to lowercase, turns slashes into
  10. # backslashes.
  11. # Other normalizations (such as optimizing '../' away) are not allowed
  12. # (this is done by normpath).
  13. # Previously, this version mapped invalid consecutive characters to a 
  14. # single '_', but this has been removed.  This functionality should 
  15. # possibly be added as a new function.
  16.  
  17. def normcase(s):
  18.     res, s = splitdrive(s)
  19.     for c in s:
  20.         if c in '/\\':
  21.             res = res + os.sep
  22.         else:
  23.             res = res + c
  24.     return string.lower(res)
  25.  
  26. # Return wheter a path is absolute.
  27. # Trivial in Posix, harder on the Mac or MS-DOS.
  28. # For DOS it is absolute if it starts with a slash or backslash (current
  29. # volume), or if a pathname after the volume letter and colon starts with
  30. # a slash or backslash.
  31.  
  32. def isabs(s):
  33.     s = splitdrive(s)[1]
  34.     return s != '' and s[:1] in '/\\'
  35.  
  36.  
  37. # Join two pathnames.
  38. # Ignore the first part if the second part is absolute.
  39. # Insert a '/' unless the first part is empty or already ends in '/'.
  40.  
  41. def join(a, b):
  42.     if isabs(b): return b
  43.     if a == '' or a[-1:] in '/\\': return a + b
  44.     # Note: join('x', '') returns 'x/'; is this what we want?
  45.     return a + os.sep + b
  46.  
  47.  
  48. # Split a path in a drive specification (a drive letter followed by a
  49. # colon) and the path specification.
  50. # It is always true that drivespec + pathspec == p
  51. def splitdrive(p):
  52.     if p[1:2] == ':':
  53.         return p[0:2], p[2:]
  54.     return '', p
  55.  
  56.  
  57. # Split a path in head (everything up to the last '/') and tail (the
  58. # rest).  If the original path ends in '/' but is not the root, this
  59. # '/' is stripped.  After the trailing '/' is stripped, the invariant
  60. # join(head, tail) == p holds.
  61. # The resulting head won't end in '/' unless it is the root.
  62.  
  63. def split(p):
  64.     d, p = splitdrive(p)
  65.     slashes = ''
  66.     while p and p[-1:] in '/\\':
  67.         slashes = slashes + p[-1]
  68.         p = p[:-1]
  69.     if p == '':
  70.         p = p + slashes
  71.     head, tail = '', ''
  72.     for c in p:
  73.         tail = tail + c
  74.         if c in '/\\':
  75.             head, tail = head + tail, ''
  76.     slashes = ''
  77.     while head and head[-1:] in '/\\':
  78.         slashes = slashes + head[-1]
  79.         head = head[:-1]
  80.     if head == '':
  81.         head = head + slashes
  82.     return d + head, tail
  83.  
  84.  
  85. # Split a path in root and extension.
  86. # The extension is everything starting at the first dot in the last
  87. # pathname component; the root is everything before that.
  88. # It is always true that root + ext == p.
  89.  
  90. def splitext(p):
  91.     root, ext = '', ''
  92.     for c in p:
  93.         if c in '/\\':
  94.             root, ext = root + ext + c, ''
  95.         elif c == '.' or ext:
  96.             ext = ext + c
  97.         else:
  98.             root = root + c
  99.     return root, ext
  100.  
  101.  
  102. # Return the tail (basename) part of a path.
  103.  
  104. def basename(p):
  105.     return split(p)[1]
  106.  
  107.  
  108. # Return the head (dirname) part of a path.
  109.  
  110. def dirname(p):
  111.     return split(p)[0]
  112.  
  113.  
  114. # Return the longest prefix of all list elements.
  115.  
  116. def commonprefix(m):
  117.     if not m: return ''
  118.     prefix = m[0]
  119.     for item in m:
  120.         for i in range(len(prefix)):
  121.             if prefix[:i+1] <> item[:i+1]:
  122.                 prefix = prefix[:i]
  123.                 if i == 0: return ''
  124.                 break
  125.     return prefix
  126.  
  127.  
  128. # Is a path a symbolic link?
  129. # This will always return false on systems where posix.lstat doesn't exist.
  130.  
  131. def islink(path):
  132.     return false
  133.  
  134.  
  135. # Does a path exist?
  136. # This is false for dangling symbolic links.
  137.  
  138. def exists(path):
  139.     try:
  140.         st = os.stat(path)
  141.     except os.error:
  142.         return 0
  143.     return 1
  144.  
  145.  
  146. # Is a path a dos directory?
  147. # This follows symbolic links, so both islink() and isdir() can be true
  148. # for the same path.
  149.  
  150. def isdir(path):
  151.     try:
  152.         st = os.stat(path)
  153.     except os.error:
  154.         return 0
  155.     return stat.S_ISDIR(st[stat.ST_MODE])
  156.  
  157.  
  158. # Is a path a regular file?
  159. # This follows symbolic links, so both islink() and isdir() can be true
  160. # for the same path.
  161.  
  162. def isfile(path):
  163.     try:
  164.         st = os.stat(path)
  165.     except os.error:
  166.         return 0
  167.     return stat.S_ISREG(st[stat.ST_MODE])
  168.  
  169.  
  170. # Are two filenames really pointing to the same file?
  171.  
  172. def samefile(f1, f2):
  173.     s1 = os.stat(f1)
  174.     s2 = os.stat(f2)
  175.     return samestat(s1, s2)
  176.  
  177.  
  178. # Are two open files really referencing the same file?
  179. # (Not necessarily the same file descriptor!)
  180. # XXX THIS IS BROKEN UNDER DOS! ST_INO seems to indicate number of reads?
  181.  
  182. def sameopenfile(fp1, fp2):
  183.     s1 = os.fstat(fp1.fileno())
  184.     s2 = os.fstat(fp2.fileno())
  185.     return samestat(s1, s2)
  186.  
  187.  
  188. # Are two stat buffers (obtained from stat, fstat or lstat)
  189. # describing the same file?
  190.  
  191. def samestat(s1, s2):
  192.     return s1[stat.ST_INO] == s2[stat.ST_INO] and \
  193.         s1[stat.ST_DEV] == s2[stat.ST_DEV]
  194.  
  195.  
  196. # Is a path a mount point?
  197. # XXX This degenerates in: 'is this the root?' on DOS
  198.  
  199. def ismount(path):
  200.     return isabs(splitdrive(path)[1])
  201.  
  202.  
  203. # Directory tree walk.
  204. # For each directory under top (including top itself, but excluding
  205. # '.' and '..'), func(arg, dirname, filenames) is called, where
  206. # dirname is the name of the directory and filenames is the list
  207. # files files (and subdirectories etc.) in the directory.
  208. # The func may modify the filenames list, to implement a filter,
  209. # or to impose a different order of visiting.
  210.  
  211. def walk(top, func, arg):
  212.     try:
  213.         names = os.listdir(top)
  214.     except os.error:
  215.         return
  216.     func(arg, top, names)
  217.     exceptions = ('.', '..')
  218.     for name in names:
  219.         if name not in exceptions:
  220.             name = join(top, name)
  221.             if isdir(name):
  222.                 walk(name, func, arg)
  223.  
  224.  
  225. # Expand paths beginning with '~' or '~user'.
  226. # '~' means $HOME; '~user' means that user's home directory.
  227. # If the path doesn't begin with '~', or if the user or $HOME is unknown,
  228. # the path is returned unchanged (leaving error reporting to whatever
  229. # function is called with the expanded path as argument).
  230. # See also module 'glob' for expansion of *, ? and [...] in pathnames.
  231. # (A function should also be defined to do full *sh-style environment
  232. # variable expansion.)
  233.  
  234. def expanduser(path):
  235.     if path[:1] <> '~':
  236.         return path
  237.     i, n = 1, len(path)
  238.     while i < n and path[i] not in '/\\':
  239.         i = i+1
  240.     if i == 1:
  241.         try:
  242.             drive=os.environ['HOMEDRIVE']
  243.         except KeyError:
  244.             drive = ''
  245.         if not os.environ.has_key('HOMEPATH'):
  246.             return path
  247.         userhome = join(drive, os.environ['HOMEPATH'])
  248.     else:
  249.         return path
  250.     return userhome + path[i:]
  251.  
  252.  
  253. # Expand paths containing shell variable substitutions.
  254. # The following rules apply:
  255. #    - no expansion within single quotes
  256. #    - no escape character, except for '$$' which is translated into '$'
  257. #    - ${varname} is accepted.
  258. #    - varnames can be made out of letters, digits and the character '_'
  259. # XXX With COMMAND.COM you can use any characters in a variable name,
  260. # XXX except '^|<>='.
  261.  
  262. varchars = string.letters + string.digits + '_-'
  263.  
  264. def expandvars(path):
  265.     if '$' not in path:
  266.         return path
  267.     res = ''
  268.     index = 0
  269.     pathlen = len(path)
  270.     while index < pathlen:
  271.         c = path[index]
  272.         if c == '\'':    # no expansion within single quotes
  273.             path = path[index + 1:]
  274.             pathlen = len(path)
  275.             try:
  276.                 index = string.index(path, '\'')
  277.                 res = res + '\'' + path[:index + 1]
  278.             except string.index_error:
  279.                 res = res + path
  280.                 index = pathlen -1
  281.         elif c == '$':    # variable or '$$'
  282.             if path[index + 1:index + 2] == '$':
  283.                 res = res + c
  284.                 index = index + 1
  285.             elif path[index + 1:index + 2] == '{':
  286.                 path = path[index+2:]
  287.                 pathlen = len(path)
  288.                 try:
  289.                     index = string.index(path, '}')
  290.                     var = path[:index]
  291.                     if os.environ.has_key(var):
  292.                         res = res + os.environ[var]
  293.                 except string.index_error:
  294.                     res = res + path
  295.                     index = pathlen - 1
  296.             else:
  297.                 var = ''
  298.                 index = index + 1
  299.                 c = path[index:index + 1]
  300.                 while c != '' and c in varchars:
  301.                     var = var + c
  302.                     index = index + 1
  303.                     c = path[index:index + 1]
  304.                 if os.environ.has_key(var):
  305.                     res = res + os.environ[var]
  306.                 if c != '':
  307.                     res = res + c
  308.         else:
  309.             res = res + c
  310.         index = index + 1
  311.     return res
  312.  
  313.  
  314. # Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
  315. # Also, components of the path are silently truncated to 8+3 notation.
  316.  
  317. def normpath(path):
  318.     path = normcase(path)
  319.     prefix, path = splitdrive(path)
  320.     while path[:1] == os.sep:
  321.         prefix = prefix + os.sep
  322.         path = path[1:]
  323.     comps = string.splitfields(path, os.sep)
  324.     i = 0
  325.     while i < len(comps):
  326.         if comps[i] == '.':
  327.             del comps[i]
  328.         elif comps[i] == '..' and i > 0 and \
  329.                       comps[i-1] not in ('', '..'):
  330.             del comps[i-1:i+1]
  331.             i = i-1
  332.         elif comps[i] == '' and i > 0 and comps[i-1] <> '':
  333.             del comps[i]
  334.         elif '.' in comps[i]:
  335.             comp = string.splitfields(comps[i], '.')
  336.             comps[i] = comp[0][:8] + '.' + comp[1][:3]
  337.             i = i+1
  338.         elif len(comps[i]) > 8:
  339.             comps[i] = comps[i][:8]
  340.             i = i+1
  341.         else:
  342.             i = i+1
  343.     # If the path is now empty, substitute '.'
  344.     if not prefix and not comps:
  345.         comps.append('.')
  346.     return prefix + string.joinfields(comps, os.sep)
  347.  
  348.